//
//  AppDatabase.swift
//  chatai
//
//  Created by Macintosh on 2023/8/7.
//

import Foundation
import GRDB

class AppDatabase {
    static let shared = AppDatabase()
    var userId = 0

    var dbPool: DatabasePool?

    init() {
        reload(UserDefaults.standard.value(forKey: UserDefaultsKey.loginUserId) as? Int ?? 0)
    }

    var migrator: DatabaseMigrator {
        var migrator = DatabaseMigrator()

        migrator.registerMigration("v1") { db in
            try db.create(table: "t_record") { t in
                t.column("recordId", .text).defaults(to: "").indexed()
                t.column("orgUrl", .text).defaults(to: "")
                t.column("title", .text).defaults(to: "")
                t.column("image", .text).defaults(to: "")
                t.column("videoUrl", .text).defaults(to: "")
                t.column("imgsStr", .text).defaults(to: "")
            }
        }
        
        return migrator
    }
}

extension AppDatabase {
    func reload(_ userId: Int) {
        if userId == self.userId && dbPool != nil {
            return
        }

        do {
            if let dbPool = self.dbPool {
                dbPool.releaseMemory()
            }
            dbPool = nil
            let fileManager = FileManager.default

            let directoryURL: URL = try fileManager
                .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            let databaseURL = directoryURL.appendingPathComponent("db_\(userId).sqlite")
            print("DB: \(databaseURL)")
            
            var isDirectory: ObjCBool = false
            if !fileManager.fileExists(atPath: directoryURL.path, isDirectory: &isDirectory) {
                try fileManager.createDirectory(atPath: directoryURL.path, withIntermediateDirectories: false)
            } else if !isDirectory.boolValue {
                print("create directoryURL Error")
                return
            }
            dbPool = try DatabasePool(path: databaseURL.path)
            if let dbPool = self.dbPool {
                try migrator.migrate(dbPool)
                self.userId = userId
            }

        } catch {
            print("DB init Error,\(userId)")
        }
    }

    func asyncWrite<T>(
        _ updates: @escaping (Database) throws -> T,
        completion: ((_ successed: Bool) -> Void)? = nil)
    {
        dbPool?.asyncWrite(updates, completion: { _, result in
            if case .success = result {
                completion?(true)
            } else if case .failure(let error) = result {
                if let e = error as? DatabaseError {
                    print("Sql Error:\(e.sql ?? ""),\(e.message ?? "")")
                } else {
                    print("Sql Error:\(error.localizedDescription)")
                }
                completion?(false)
            }
        })
    }

}
